#!/bin/bash
#descript: install openvpn server on centos 6、7 server
#http://www.jb51.net/article/137995.htm(openvpn2.4.5,easy-rsa3.0.3)
SOFTDIR="/opt/tools"
DATE="`date +"%y-%m-%d %H:%M:%S"`"
OUT_INT="eth0"
IN_INT="eth1"
OUTIP="`ifconfig ${OUT_INT}|grep 'inet'|grep -v "inet6"|awk '{print $2}'`"
INIP="`ifconfig ${IN_INT}|grep 'inet'|grep -v "inet6"|awk '{print $2}'`"
KERNEL_VERSION="`cat /etc/redhat-release |awk '{print $4}'`"
HOSTNAME="`hostname`"
PORT="51175"
VPN_IP="172.17.2.0"
VPN_VER="2.3.16"
IN_NET="192.168.20.0 255.255.255.0"
function init() {
	#configure epel yum source
	yum -y install ntpdate vim wget gcc gcc-c++ tree autoconf
        cd /etc/yum.repos.d/
	if [ "$(uname -r|cut -d- -f2|cut -d. -f2)" == "el7" ];then
		if [ ! -f epel-7.repo ];then
			wget -O /etc/yum.repos.d/epel-7.repo http://mirrors.aliyun.com/repo/epel-7.repo
		fi
	elif [ "$(uname -r|cut -d- -f2|cut -d. -f2)" == "el6" ];then
		if [ ! -f epel-6.repo ];then
                        wget -O /etc/yum.repos.d/epel-6.repo http://mirrors.aliyun.com/repo/epel-6.repo
                fi
	else
		echo "The system is not centos"
		exit 1
	fi
	#Configuration time synchronization
	/usr/sbin/ntpdate time1.aliyun.com
	crontab -l >/opt/crontab.bak && echo "*/2 * * * * /usr/sbin/ntpdate time1.aliyun.com &>/dev/null 2>&1" >> /opt/crontab.bak && crontab /opt/crontab.bak
	#Configure firewall
	 sed -i "s#SELINUX=enforcing#SELINUX=disabled#g" /etc/selinux/config
	 setenforce 0
	 if [ "$(uname -r|cut -d- -f2|cut -d. -f2)" == "el7" ];then
		systemctl start firewalld 
		firewall-cmd --add-service=openvpn
		firewall-cmd --add-service=openvpn --permanent
		firewall-cmd --add-interface=tun0
		firewall-cmd --add-interface=tun0 --permanent
		firewall-cmd --add-port=${PORT}/tcp
		firewall-cmd --add-port=${PORT}/udp
		firewall-cmd --add-port=${PORT}/tcp --permanent
		firewall-cmd --add-port=${PORT}/udp  --permanent
		firewall-cmd --zone=public --add-masquerade --permanent
		firewall-cmd reload
	fi
	if [ "$(uname -r|cut -d- -f2|cut -d. -f2)" == "el6" ];then
		iptables -I INPUT -p tcp --dport ${PORT} -j ACCEPT
		iptables -I INPUT -p udp --dport ${PORT} -j ACCEPT
		iptables -t nat -A POSTROUTING -s ${VPN_IP}/24 -j SNAT --to-source ${INIP}
		service iptables save 
		service iptables restart
	fi
}
function install_openvpn(){
	yum -y install openssh-server autoconf expect openssl openssl-devel pam-devel lzo lzo-devel
	[ ! -d $SOFTDIR ] && mkdir -p $SOFTDIR
	cd $SOFTDIR && [ ! -f openvpn-${VPN_VER}.tar.gz ] && wget http://soft.51yuki.cn/openvpn-${VPN_VER}.tar.gz
	tar xf openvpn-${VPN_VER}.tar.gz && cd openvpn-${VPN_VER}
	./configure --prefix=/usr/local/openvpn && make && make install
	cd $SOFTDIR && [ ! -f EasyRSA-2.2.2.tgz ] && wget http://soft.51yuki.cn/EasyRSA-2.2.2.tgz
	tar xf EasyRSA-2.2.2.tgz -C /usr/local/openvpn/
	cd /usr/local/openvpn/EasyRSA-2.2.2/ && cp vars{,.ori}
        sed -i "s#US#CN#" vars
        sed -i "s#CA#SH#" vars
        sed -i "s#SanFrancisco#shanghai#" vars
        sed -i "s#Fort-Funston#al#" vars
        sed -i "s#me@myhost.mydomain#851628816@qq.com#" vars
        sed -i "s#MyOrganizationalUnit#alsops#" vars
}
function Configure_OPENVPN(){
	#CA certificate
	#在执行configure_OPENVPN 必须需要进入/usr/local/openvpn/EasyRSA-2.2.2/目录，执行source vars 和 ./clean-all,如下
	#[root@node5 EasyRSA-2.2.2]# source vars
	#NOTE: If you run ./clean-all, I will be doing a rm -rf on /usr/local/openvpn/EasyRSA-2.2.2/keys
	#[root@node5 EasyRSA-2.2.2]# ./clean-all (第一次运行使用，以后生成客户端正式就不要运行，否则所有证书会情况，所以这里就不写在脚本里
	cd /usr/local/openvpn/EasyRSA-2.2.2/ && chmod u+x vars
	/usr/local/openvpn/EasyRSA-2.2.2/vars
	/usr/local/openvpn/EasyRSA-2.2.2/clean-all
	/usr/bin/expect <<EOF
		spawn /usr/local/openvpn/EasyRSA-2.2.2/build-ca
		expect "Country" {send "\r"} 
		expect "State" {send "\r"}
		expect "Locality" {send "\r"}
		expect "Organization" {send "\r"}
		expect "Organizational" {send "\r"}
		expect "Common Name" {send "\r"}
		expect "Name" {send "\r"}
		expect "Email Address" {send "\r"}
		expect eof
EOF
	#DH
	/usr/local/openvpn/EasyRSA-2.2.2/build-dh
	#Server Certificate
	/usr/bin/expect <<EOF
		spawn /usr/local/openvpn/EasyRSA-2.2.2/build-key-server server
		expect "Country" {send "\r"} 
		expect "State" {send "\r"}
		expect "Locality" {send "\r"}
		expect "Organization" {send "\r"}
		expect "Organizational" {send "\r"}
		expect "Common Name" {send "\r"}
		expect "Name" {send "\r"}
		expect "Email Address" {send "\r"}
		expect "A challenge" {send "\r"}
		expect "An optional" {send "\r"}
		expect "Sign"  {send "y\r"}
		expect "1 out of" {send "y\r"}
		expect eof
EOF
	
	#configure openvpn file
	cd /usr/local/openvpn && [ ! -d server ] && mkdir server && cd server/
	cat >/usr/local/openvpn/server/server.conf <<EOF
local $OUTIP
port $PORT
proto tcp
dev tun
ca /usr/local/openvpn/server/ca.crt
cert /usr/local/openvpn/server/server.crt
key /usr/local/openvpn/server/server.key  # This file should be kept secret
dh /usr/local/openvpn/server/dh2048.pem
server ${VPN_IP} 255.255.255.0
ifconfig-pool-persist ipp.txt
push "route ${IN_NET}"
client-to-client
duplicate-cn
keepalive 10 120
tls-auth ta.key 0 # This file is secret
cipher AES-256-CBC
comp-lzo
persist-key
persist-tun
status openvpn-status.log
log /var/log/openvpn
verb 3
EOF
	  /usr/bin/cp -rf /usr/local/openvpn/EasyRSA-2.2.2/keys/{ca.crt,ca.key,server.crt,server.key,dh2048.pem} /usr/local/openvpn/server/
          ln -sv /usr/local/openvpn/sbin/openvpn /usr/sbin/openvpn
          cd /usr/local/openvpn/server
	  openvpn --genkey --secret ta.key
	  #copy openvpn start scripts
	  /usr/bin/cp /opt/tools/openvpn-${VPN_VER}/distro/rpm/openvpn.init.d.rhel /etc/init.d/openvpn
	  sed -i "s#work=/etc/openvpn#work=/usr/local/openvpn/server#" /etc/init.d/openvpn
          chmod 700 /etc/init.d/openvpn && chkconfig --add openvpn && chkconfig openvpn on
	  service openvpn start
          if [ "`ss -tunlp|grep ${PORT}|awk -F: '{print $2}'|awk '{print $1}'`" == "$PORT" ];then
		echo "openvpn start succfull"
	   else
		echo "openvpn start fail"
	  fi
}
function Configure_Client(){
	read -p "please input client name:<如louis>" CLIENT
	cd /usr/local/openvpn/EasyRSA-2.2.2
	/usr/bin/expect <<EOF
                spawn /usr/local/openvpn/EasyRSA-2.2.2/build-key $CLIENT
                expect "Country" {send "\r"} 
                expect "State" {send "\r"}
                expect "Locality" {send "\r"}
                expect "Organization" {send "\r"}
                expect "Organizational" {send "\r"}
                expect "Common Name" {send "\r"}
                expect "Name" {send "\r"}
                expect "Email Address" {send "\r"}
                expect "A challenge" {send "\r"}
                expect "An optional" {send "\r"}
                expect "Sign"  {send "y\r"}
                expect "1 out of" {send "y\r"}
                expect eof
EOF
     
     cd /usr/local/openvpn && [ ! -d client ] && mkdir client && cd client
     /usr/bin/cp /usr/local/openvpn/EasyRSA-2.2.2/keys/{ca.crt,${CLIENT}.crt,${CLIENT}.key} /usr/local/openvpn/client/
     cp /usr/local/openvpn/server/ta.key /usr/local/openvpn/client/
     cat >/usr/local/openvpn/client/${CLIENT}.conf <<EOF
client
dev tun
proto tcp
remote $OUTIP  $PORT
resolv-retry infinite
nobind
persist-key
persist-tun
ca ca.crt
cert ${CLIENT}.crt
key ${CLIENT}.key
remote-cert-tls server
tls-auth ta.key 1
cipher AES-256-CBC
comp-lzo
verb 3
EOF
}
function Revoke_Client(){
	#执行回收客户端证书的，必须要重启openvpn才能生效，有可能不造成其他客户端vpn中断
	read -p "Please Input Client Name:" CNAME
	cd /usr/local/openvpn/EasyRSA-2.2.2
	./revoke-full $CNAME
	/usr/bin/cp /usr/local/openvpn/EasyRSA-2.2.2/keys/crl.pem /usr/local/openvpn/server/
	grep "crl-verify" /usr/local/openvpn/server/server.conf
	if [ $? -ne 0 ];then
		echo "crl-verify /usr/local/openvpn/server/crl.pem" >> /usr/local/openvpn/server/server.conf
	fi
	#重启openvpn服务
	service openvpn stop && service openvpn start
	if [ ` ps -ef|grep openvpn|wc -l` -gt 1 ];then
		echo "openvpn start succfull"
	else
		echo "openvpn start fail"
	fi
}
 	
cat <<EOF
-----------------------------------------------------------------
		Install the openvpn server
----------------------------------------------------------------
| DATE     		 :  $DATE
| IP      		 :  $OUTIP
| KERNEL_VERSION         :  ${KERNEL_VERSION}
| HOSTNAME               :  $HOSTNAME
---------------------------------------------------------------
|*********Please Enter your Choice:***************************|
(1) Initialize the environment
(2) install openvpn software
(3) configure openvpn server
(4) configure openvpn client
(5) revoke client  certificate
(6) quit
---------------------------------------------------------------
EOF
read -p "please enter your choice:" input
case $input in
1)
   init
   ;;
2)
  install_openvpn
  ;;
3)
  Configure_OPENVPN
  ;;
4)
  Configure_Client
  ;;
5)
  Revoke_Client
  ;;
6)
  exit 1
esac
